#include "os_lib.h"
#include "os_dbg.h"
#include "os_types.h"
#include "os_sched.h"
#include "os_plat.h"
#include <stdarg.h>

#if OS_LIB_USE_OWN
/**
 * 字符串复制，最多复制前N字节
*/
char * os_strncpy (char *dest, const char *src, int size) {
    os_param_failed((dest == OS_NULL) || (src == OS_NULL) || (size == 0), OS_NULL);

    // 建立两个新的局部方便，方便随时观察dest和src原始值
    char *dest_c = dest;
    const char *src_c = src;

    while (size--) {
        char c;

        c = *dest_c++ = *src_c++;   // 复制后取最后的值
        if (c == '\0') {
            // 遇到结束符, 其余继续填充空
            while (size--) {
                *dest_c++ = '\0';
            }

            break;
        }
    }
    return (dest);
}

/**
 * 内存填充
*/
void * os_memset (void * mem, int v, int count) {
    os_param_failed(mem == OS_NULL, OS_NULL);
    os_param_failed(count == 0, mem);

    char * c = (char *)mem;

    while (count--) {
        *c++ = v;
    }
    return mem;
}

/**
 * 内存复制
*/
void * os_memcpy (void * dest, const void * src, int count) {
    os_param_failed(dest == src, dest);
    os_param_failed(count == 0, dest);
    
    // 要考虑两块内存的位置是否有重叠，不然可能导致复制出现问题
    // dest在低地址，或者dest在后边但是完全超出src尾部
    if ((dest <= src) || ((uint8_t *)dest >= ((uint8_t *)src + count))) {
        uint8_t * dest_c = (uint8_t *)dest;
        const uint8_t * src_c = (const uint8_t *)src;
        
        // 从头部开始复制
        while (count--) {
            *dest_c++ = *src_c++;
        }
    } else {
        // 有重叠
        uint8_t * dest_c = (uint8_t *)dest + count - 1;
        const uint8_t * src_c = (const uint8_t *)src + count - 1;

        // 从尾部开始复制
        while (count--) {
            *dest_c-- = *src_c--;
        }
    }

    return dest;
}

/**
 * 格式化打印字符串
 */
#if OS_DBG_PRINT_ENABLE
void os_printf (const char * fmt, ...) {    
    va_list args;

    va_start(args, fmt);

    const char * str = fmt;
    char c = *str;
    while ((c = *str++) != '\0') {
        // 非以%开头的普通字符，写入接收缓存
        if (c != '%') {
            os_plat_putc(c);
            continue;
        }

        // 以%开头的格式化字符串
        c = *str++;         // 跳过%号
        if (c == '\0') {
            return;
        }

        // 跳过其它区域，直接检查生成的类型
        switch (c) {
            case 'c': {
                // 普通字符
                os_plat_putc(c);
                break;
            }
            case 's': {
                // 字符串
                char * s = va_arg(args, char *);
                while (*s) {
                    os_plat_putc(*s++);
                }
                break;
            }
            case 'u': {
                unsigned int d = va_arg(args, unsigned int);

                char temp[12];
                int i = 0;
                do {
                    temp[i++] = '0' + d % 10;
                    d /= 10;
                } while (d);

                while (i > 0) {
                    os_plat_putc(temp[--i]);
                }
                break;
            }
            case 'd': {
                // 整数转换
                int d = va_arg(args, int);
                if (d < 0) {
                    os_plat_putc('-');
                    d = -d;
                }

                char temp[12];
                int i = 0;
                do {
                    temp[i++] = '0' + d % 10;
                    d /= 10;
                } while (d);
                while (i > 0) {
                    os_plat_putc(temp[--i]);
                }
                break;
            }
            default: {
                os_plat_putc(c);
                break;
            }
        }
    }
    va_end(args);
}
#endif

#endif // OS_LIB_USE_OWN
